package graphics;

import java.util.HashMap;
import java.util.Map;

import game.Game;
import game.Player;

import com.marakana.obolo.GameActivity;
import com.marakana.obolo.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import android.graphics.Paint.Style;
import android.graphics.Point;

import android.util.AttributeSet;

import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class PanelGame extends SurfaceView implements SurfaceHolder.Callback {

	public static float mWidth;
	public static float mHeight;

	private Map<String, Integer> numbers;
	private Point txtRivalPosition, txtUserPosition, rivalDeckFirstPosition,
			userDeckFirstPosition, boardFirstPosition;

	private Paint paint;
	private ThreadGraphics threadGraphics;

	private int backgroundId, screenWidth, screenHeight;
	private boolean iaVersus;

	private Game game;
	private GameActivity gameActivity;

	private PanelCard touchedCardDeck, touchedCardBoard;
	private PanelCard[] rivalCards, userCards;
	private PanelCard[][] boardGame;

	public PanelGame(Context context) {
		super(context);
		init();
	}

	public PanelGame(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public PanelGame(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init() {
		getHolder().addCallback(this);
		threadGraphics = new ThreadGraphics(getHolder(), this);
		setFocusable(true);
		paint = new Paint();
		numbers = new HashMap<String, Integer>();
		iaVersus = false;
		initializeNumbers();

	}
	
	
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		mWidth = width;
		mHeight = height;
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (!threadGraphics.isAlive()) {
			threadGraphics = new ThreadGraphics(getHolder(), this);
			threadGraphics.setRunning(true);
			threadGraphics.start();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		boolean retry = true;
		threadGraphics.setRunning(false);
		while (retry) {
			try {
				threadGraphics.join();
				retry = false;
			} catch (InterruptedException e) {
				// we will try it again and again...
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int x = (int) event.getX();
		int y = (int) event.getY();

		PanelCard lastTouch = null;

		if (!iaVersus){
			if (touchedCardDeck == null) {
				touchedCardDeck = touchCard(x, y);
			} else {
				lastTouch = touchedCardDeck;
				touchedCardDeck = touchCard(x, y);
				if (touchedCardDeck != null
						&& touchedCardDeck.getPlace() == PanelCard.BOARD_PLACE) {
					touchedCardBoard = touchedCardDeck;
					touchedCardDeck = lastTouch;
				} else if (touchedCardDeck == null) {
					touchedCardDeck = lastTouch;
				} else {
					touchedCardDeck = null;
					touchedCardBoard = null;
				}
			}
			if (touchedCardDeck != null && touchedCardBoard != null) {
				gameActivity.setOboloFromDeck(touchedCardDeck);
				gameActivity.setOboloFromBoard(touchedCardBoard);
				/*
				 * touchedCardBoard.setObolo(touchedCardDeck.getObolo());
				 * touchedCardDeck.setObolo(null);
				 */
				touchedCardDeck = null;
				touchedCardBoard = null;
				gameActivity.playObolo();
			}
		}
		

		

		return super.onTouchEvent(event);
	}

	private PanelCard touchCard(int x, int y) {
		PanelCard card = null;

		int index = 0;

		int row, column;
		row = 0;
		column = 0;
		while (card == null && row < boardGame.length) {
			while (card == null && column < boardGame[row].length) {
				if (boardGame[row][column].getObolo() == null
						&& (x >= boardGame[row][column].getPosition().x
								&& x <= (boardGame[row][column].getPosition().x + boardGame[row][column]
										.getOboloWidth())
								&& y >= boardGame[row][column].getPosition().y && y <= (boardGame[row][column]
								.getPosition().y + boardGame[row][column]
								.getOboloHeight()))) {
					card = boardGame[row][column];
				}
				column++;
			}
			row++;
			column = 0;
		}

		if (gameActivity.hasTurn(Game.RIVAL)
				&& rivalCards[0].getPlayer().isHuman()) {
			while (card == null && index < rivalCards.length) {
				if (rivalCards[index].getObolo() != null
						&& (x >= rivalCards[index].getPosition().x
								&& x <= (rivalCards[index].getPosition().x + rivalCards[index]
										.getOboloWidth())
								&& y >= rivalCards[index].getPosition().y && y <= (rivalCards[index]
								.getPosition().y + rivalCards[index]
								.getOboloHeight()))) {
					card = rivalCards[index];
				}
				index++;
			}
		}

		index = 0;
		if (gameActivity.hasTurn(Game.USER)
				&& userCards[0].getPlayer().isHuman()) {
			while (card == null && index < userCards.length) {
				if (userCards[index].getObolo() != null
						&& (x >= userCards[index].getPosition().x
								&& x <= (userCards[index].getPosition().x + userCards[index]
										.getOboloWidth())
								&& y >= userCards[index].getPosition().y && y <= (userCards[index]
								.getPosition().y + userCards[index]
								.getOboloHeight()))) {
					card = userCards[index];
				}
				index++;
			}
		}

		return card;
	}

	public void setIaVersus(boolean iaVersus) {
		this.iaVersus = iaVersus;
	}

	public void setSize(int width, int height) {
		screenWidth = width;
		screenHeight = height;
	}

	public void setGame(Game game) {
		this.game = game;
	}

	public void setGameActivity(GameActivity gameActivity) {
		this.gameActivity = gameActivity;
	}

	public void setBackgroundId(int background) {
		backgroundId = background;
	}

	/*
	 * private void setPositions() { int left, top; left = 0; top = 0;
	 * 
	 * int padding = screenHeight * 2 / 100; left = padding; top = padding * 2;
	 * txtRivalPosition = new Point(left, top);
	 * 
	 * int textSize = screenHeight * 4 / 100; int newCardWidth = (screenWidth /
	 * rivalCards.length) - padding; int newCardHeight = (screenHeight - (2 *
	 * textSize) - (10 * padding)) / (boardGame.length + 2);
	 * 
	 * left = 0; top += textSize;
	 * 
	 * for (int index = 0; index < rivalCards.length; index++) {
	 * rivalDeckFirstPosition = new Point(left, top);
	 * rivalCards[index].setOboloWidth(newCardWidth);
	 * rivalCards[index].setOboloHeight(newCardHeight);
	 * rivalCards[index].setPosition(rivalDeckFirstPosition); left +=
	 * newCardWidth + padding; }
	 * 
	 * left = (screenWidth - (newCardWidth * boardGame[0].length) -
	 * ((boardGame[0].length) * padding)) / 2; top += newCardHeight + padding;
	 * 
	 * for (int row = 0; row < boardGame.length; row++) { for (int column = 0;
	 * column < boardGame[row].length; column++) { boardFirstPosition = new
	 * Point(left, top); boardGame[row][column].setOboloWidth(newCardWidth);
	 * boardGame[row][column].setOboloHeight(newCardHeight);
	 * boardGame[row][column].setPosition(boardFirstPosition); left +=
	 * newCardWidth + padding; } top += newCardHeight + padding; left =
	 * (screenWidth - (newCardWidth * boardGame[0].length) -
	 * ((boardGame[0].length) * padding)) / 2; }
	 * 
	 * left = padding; top += padding * 2; txtUserPosition = new Point(left,
	 * top); left = 0; top += textSize;
	 * 
	 * for (int index = 0; index < userCards.length; index++) {
	 * userDeckFirstPosition = new Point(left, top);
	 * userCards[index].setOboloWidth(newCardWidth);
	 * userCards[index].setOboloHeight(newCardHeight);
	 * userCards[index].setPosition(userDeckFirstPosition); left += newCardWidth
	 * + padding; } }
	 */

	public void setCards(PanelCard[] rivalCards, PanelCard[] userCards,
			PanelCard[][] boardGame) {
		// this.rivalCards = new PanelCard[rivalCards.length];
		this.rivalCards = rivalCards;
		// this.userCards = new PanelCard[userCards.length];
		this.userCards = userCards;
		// this.boardGame = new
		// PanelCard[boardGame.length][boardGame[0].length];
		this.boardGame = boardGame;
		// setPositions();
	}

	

	// Asocia cada recurso (drawable) a un String dentro del hashMap numbers
	private void initializeNumbers() {
		numbers.put("1", R.drawable.uno);
		numbers.put("2", R.drawable.dos);
		numbers.put("3", R.drawable.tres);
		numbers.put("4", R.drawable.cuatro);
		numbers.put("5", R.drawable.cinco);
		numbers.put("6", R.drawable.seis);
		numbers.put("7", R.drawable.siete);
		numbers.put("8", R.drawable.ocho);
		numbers.put("9", R.drawable.nueve);
		numbers.put("sword", R.drawable.sword);
		numbers.put("shield", R.drawable.shield);
	}

	public void disablePlayers(Player rival, Player user) {
		if (!rival.isHuman() && !user.isHuman()) {
			iaVersus = true;			
		}		
	}

	@Override
	public void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		Bitmap background;
		background = BitmapFactory.decodeResource(getResources(), backgroundId);
		background = Bitmap.createScaledBitmap(background, screenWidth,
				screenHeight, true);
		canvas.drawBitmap(background, 0, 0, null);

		paint.setColor(Color.WHITE);
		paint.setStyle(Style.FILL);
		paint.setAntiAlias(true);

		int left, top;
		left = 0;
		top = 0;

		int padding = screenHeight * 2 / 100;
		left = padding;
		top = padding * 2;
		txtRivalPosition = new Point(left, top);

		int textSize = screenHeight * 4 / 100;
		int newCardWidth = (screenWidth / rivalCards.length) - padding;
		int newCardHeight = (screenHeight - (2 * textSize) - (10 * padding))
				/ (boardGame.length + 2);

		paint.setTextSize(textSize);
		canvas.drawText(game.getPlayerName(Game.RIVAL), txtRivalPosition.x,
				txtRivalPosition.y, paint);

		String skillDraw;
		// Altura de una skill
		int skillHeight = rivalCards[0].getOboloHeight() / 3;

		// Ancho de una skill
		int skillWidth = rivalCards[0].getOboloWidth() / 3;

		Bitmap card;

		left = 0;
		top += textSize;

		synchronized (rivalCards) {
			for (int index = 0; index < rivalCards.length; index++) {
				if (rivalCards[index].getObolo() != null) {
					rivalDeckFirstPosition = new Point(left, top);
					rivalCards[index].setOboloWidth(newCardWidth);
					rivalCards[index].setOboloHeight(newCardHeight);
					rivalCards[index].setPosition(rivalDeckFirstPosition);
					left += newCardWidth + padding;
					card = BitmapFactory.decodeResource(getResources(),
							R.drawable.coinrival);
					card = Bitmap.createScaledBitmap(card,
							rivalCards[index].getOboloWidth(),
							rivalCards[index].getOboloHeight(), true);
					canvas.drawBitmap(card, rivalCards[index].getPosition().x,
							rivalCards[index].getPosition().y, null);

					// Pinta el Nord
					skillDraw = rivalCards[index].getObolo().getNorthName();
					drawSkill(canvas, skillDraw, "norte",
							rivalCards[index].getPosition().x,
							rivalCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Este
					skillDraw = rivalCards[index].getObolo().getEastName();
					drawSkill(canvas, skillDraw, "este",
							rivalCards[index].getPosition().x,
							rivalCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Sud
					skillDraw = rivalCards[index].getObolo().getSouthName();
					drawSkill(canvas, skillDraw, "sud",
							rivalCards[index].getPosition().x,
							rivalCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Oeste
					skillDraw = rivalCards[index].getObolo().getWestName();
					drawSkill(canvas, skillDraw, "oeste",
							rivalCards[index].getPosition().x,
							rivalCards[index].getPosition().y, skillHeight,
							skillWidth);
				}
			}
		}
		

		left = (screenWidth - (newCardWidth * boardGame[0].length) - ((boardGame[0].length) * padding)) / 2;
		top += newCardHeight + padding;

		synchronized (boardGame) {
			for (int row = 0; row < boardGame.length; row++) {
				for (int column = 0; column < boardGame[row].length; column++) {
					boardFirstPosition = new Point(left, top);
					boardGame[row][column].setOboloWidth(newCardWidth);
					boardGame[row][column].setOboloHeight(newCardHeight);
					boardGame[row][column].setPosition(boardFirstPosition);
					left += newCardWidth + padding;
					if (boardGame[row][column].getObolo() == null) {
						card = BitmapFactory.decodeResource(getResources(),
								R.drawable.coinvoid);
						card = Bitmap.createScaledBitmap(card,
								boardGame[row][column].getOboloWidth(),
								boardGame[row][column].getOboloHeight(), true);
						canvas.drawBitmap(card,
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y, null);

					} else {
						if (boardGame[row][column].getObolo().getOwner() == Game.RIVAL) {

							card = BitmapFactory.decodeResource(getResources(),
									R.drawable.coinrival);
						} else {
							card = BitmapFactory.decodeResource(getResources(),
									R.drawable.coinuser);
						}
						card = Bitmap.createScaledBitmap(card,
								boardGame[row][column].getOboloWidth(),
								boardGame[row][column].getOboloHeight(), true);
						canvas.drawBitmap(card,
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y, null);

						// Pinta el Nord
						skillDraw = boardGame[row][column].getObolo()
								.getNorthName();
						drawSkill(canvas, skillDraw, "norte",
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y,
								skillHeight, skillWidth);

						// Pinta el Este
						skillDraw = boardGame[row][column].getObolo().getEastName();
						drawSkill(canvas, skillDraw, "este",
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y,
								skillHeight, skillWidth);

						// Pinta el Sud
						skillDraw = boardGame[row][column].getObolo()
								.getSouthName();
						drawSkill(canvas, skillDraw, "sud",
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y,
								skillHeight, skillWidth);

						// Pinta el Oeste
						skillDraw = boardGame[row][column].getObolo().getWestName();
						drawSkill(canvas, skillDraw, "oeste",
								boardGame[row][column].getPosition().x,
								boardGame[row][column].getPosition().y,
								skillHeight, skillWidth);
					}
				}
				top += newCardHeight + padding;
				left = (screenWidth - (newCardWidth * boardGame[0].length) - ((boardGame[0].length) * padding)) / 2;
			}
		}
	

		left = padding;
		top += padding * 2;
		txtUserPosition = new Point(left, top);		
		canvas.drawText(game.getPlayerName(Game.USER), txtUserPosition.x,
				txtUserPosition.y, paint);
		
		left = 0;
		top += textSize;

		synchronized (userCards) {
			for (int index = 0; index < userCards.length; index++) {
				if (userCards[index].getObolo() != null) {
					userDeckFirstPosition = new Point(left, top);
					userCards[index].setOboloWidth(newCardWidth);
					userCards[index].setOboloHeight(newCardHeight);
					userCards[index].setPosition(userDeckFirstPosition);
					left += newCardWidth + padding;
					card = BitmapFactory.decodeResource(getResources(),
							R.drawable.coinuser);
					card = Bitmap.createScaledBitmap(card,
							userCards[index].getOboloWidth(),
							userCards[index].getOboloHeight(), true);
					canvas.drawBitmap(card, userCards[index].getPosition().x,
							userCards[index].getPosition().y, null);

					// Pinta el Nord
					skillDraw = userCards[index].getObolo().getNorthName();
					drawSkill(canvas, skillDraw, "norte",
							userCards[index].getPosition().x,
							userCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Este
					skillDraw = userCards[index].getObolo().getEastName();
					drawSkill(canvas, skillDraw, "este",
							userCards[index].getPosition().x,
							userCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Sud
					skillDraw = userCards[index].getObolo().getSouthName();
					drawSkill(canvas, skillDraw, "sud",
							userCards[index].getPosition().x,
							userCards[index].getPosition().y, skillHeight,
							skillWidth);

					// Pinta el Oeste
					skillDraw = userCards[index].getObolo().getWestName();
					drawSkill(canvas, skillDraw, "oeste",
							userCards[index].getPosition().x,
							userCards[index].getPosition().y, skillHeight,
							skillWidth);
				}
			}
		}
		
	}

	private void drawSkill(Canvas canvas, String skillDraw, String position,
			int x, int y, int skillHeight, int skillWidth) {

		int left, top;
		left = 0;
		top = 0;
		if (position.compareTo("norte") == 0) {
			left = x + skillWidth;
			top = y;
		} else if (position.compareTo("este") == 0) {
			left = x + 2 * skillWidth;
			top = y + skillHeight;
		} else if (position.compareTo("sud") == 0) {
			left = x + skillWidth;
			top = y + 2 * skillHeight;
		} else if (position.compareTo("oeste") == 0) {
			left = x;
			top = y + skillHeight;
		}

		Bitmap skillIcon;
		skillIcon = BitmapFactory.decodeResource(getResources(),
				numbers.get(skillDraw));
		skillIcon = Bitmap.createScaledBitmap(skillIcon, skillWidth,
				skillHeight, true);
		canvas.drawBitmap(skillIcon, left, top, null);
	}
}
